home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-08-20 | 13.4 KB | 337 lines | [TEXT/MPCC] |
- Janus 0.1 Release Notes / Documentation / Examples
- Peter Creath
- pjcreath@phoenix.princeton.edu
- -------------------------------------------------------------------------
- - What the hell is Janus?
-
- Think of this as the PPC native equivalent of the ResEdit CODE editor.
-
- In layman's terms, Janus is a fat binary (of course) which lets you find the
- PowerPC native code corresponding to 680x0 code. Now you can patch your
- favorite native games to give yourself infinite ammo and lives too!
-
- NOTE: This is not for the faint of heart. If you can figure out the 680x0
- patches on your own, this is for you. If not, find somebody who can.
-
- In technical terms, Janus is (in its current incarnation) a reference tracer for
- PowerPC-native code. This means it can search for references to a Toolbox
- trap (aka "symbol" in the new PPC way of doing things) and references to a
- subroutine, and can tell you what trap is being dispatched by what subroutine.
-
- -------------------------------------------------------------------------
- - Symbols? Trap dispatch subroutines? HUH?
-
- If you REALLY understand how PPC native code works, you can probably skip this
- section.
-
- In the old 680x0 way of doing things, the opcodes from 0xA000 to 0xAFFF were
- reserved for "A-Traps". Any A-Trap then called the subroutine referred to by the
- trap table. Apple used this trap mechanism to implement their Toolbox. If you
- have never seen _WaitNextEvent or _Debugger or some such, you need to brush up
- on your 680x0 assembly.
-
- In the PowerPC world, we still have traps, but Apple decided to do something a
- little more clever. Patching traps is a pain in the ass, and is slow. Traps are
- essential shared code, so why not have a universal dispatcher for generic symbols
- and dispatch traps that way? This is exactly what Apple did.
-
- When a PowerPC native program wishes to call a trap, it sets up the function
- parameters in typical PPC calling fashion, then it sets two registers to the
- first 8 bytes of the trap name. (ie: "WaitNext") This small fragment of code
- (which is generated for each trap used) is called the symbol (or trap) glue.
-
- In addition, when a PPC native application launches, it exports a symbol table
- (part of the as-of-yet-undocumented PEF format) which the Code Fragment
- Manager checks to make sure it can resolve all the symbols. (ie: It makes
- sure it knows how to handle Debugger or ParamText, or whatever else
- may be exported).
-
- This is where Janus comes in.
-
- -------------------------------------------------------------------------
- - What does Janus do?
-
- Janus reads in the PEF symbol table and lets you do all sorts of nifty stuff with
- it:
- o You can list all the symbols and their associated numbers. This, if nothing
- else, tells you what traps are being called in the program. (You also
- need the trap numbers for the other cool stuff you can do.)
-
- o You can search for references to the symbols (or, actually, their
- glue code). In other words, if you enter in the symbol number for
- GetNextEvent, it will show you every place GetNextEvent() is called
- in the native code.
-
- o You can find out what symbol is called by a specific glue routine.
-
- o You can search for references to any subroutine at all.
-
- -------------------------------------------------------------------------
- - Why do I care?
-
- Well, there is no native PPC debugger (a la MacsBug). OK, so I lied, there is a
- 2-machine debugger, but not all of us have the luxury of having two machines
- adjacent and networked. This makes patching native code a real hassle (or
- impossibility usually).
-
- There's also no native equivalent to the ResEdit CODE editor, with its
- searching for references and such.
-
- What you can do now is, once you have made a patch to 680x0 code, you can
- search around your patch for "landmarks", the most convenient of which
- are traps (or symbols). Then you search for those same landmarks in the
- native code using Janus, thereby narrowing down your search to a few
- dozen native instructions (if you're lucky). Naturally, things aren't always
- this easy, but this does cover the bulk of native software out there.
-
- -------------------------------------------------------------------------
- - General instructions
-
- I use PowerPCdisas for my native code wanderings. Hence, Janus prints
- the code offsets in terms of their position in the data fork (not their position
- in the PEF container).
-
- -------------------------------------------------------------------------
- - Patching and native code tips, etc.
-
- 4800xxxx is a BRA statement
- 60000000 is a NOP statement
-
- "mflr" occurrs at the beginning of every subroutine
- "blr" occurs at the end of every subroutine
-
- There are often many return points within a subroutine. In 68k code, there
- was usually just one RTS. In native code, rather than BRA to the end (over
- a bunch of code), it just RTS's immediately.
-
- Code within segments is (so far) always in the same order in 68k & PPC
- native, however the native code IS NOT ALWAYS in the same order as
- the segments themselves. In other words, your PPC code could have
- the equivalent object code to segment 10, then 3, then 4, then 7, then
- 1, and so on. Thus, if you're having trouble finding a piece of equivalent
- code, look for landmarks near the beginning and end of your code segment
- and find out where your code segment is in the native code. (This is
- a generally useful practice, as correlating hundreds of occurrences of
- traps can be hard on the eyes!)
-
- You definitely need the Motorola PowerPC™ 601 User's Manual. It's about
- $5 or so (or whatever shipping costs).
- (IBM part # 52G7484, (800) 769-3772)
- (Motorola part # MPC601UM/AD, (800) 521-6274)
-
- -------------------------------------------------------------------------
- - Limitations, future plans, etc.
-
- o Janus only reads PEF (not XCOFF) files.
- o Janus only looks in applications with the native code in the data fork.
- o Janus only looks in the first code container in the PEF.
- o Janus needs enough RAM to read in the entire code fragment.
-
- o If I run across some XCOFF files (enough to reverse engineer Apple's
- implementation), I will add that functionality.
- o If you find non-applications with PEF data, let me know.
- o If you find any applications with more than one code container, let
- me know.
- o I will leave the RAM requirement as-is, for speed reasons.
-
- Originally, this was going to entirely automate the matching process between
- 68k code and PowerPC native code. However, the need for SOME utility forced
- me to throw together the components I had finished and toss it out the door.
-
- That and the lack of interface make this version 0.1. 1.0 should automate
- the task and save a data file (which will also allow you to match code between
- versions, so you don't have to re-find your patch for each release). It'll also
- have an interface.
-
- Hopefully, I'll also have a built-in disassembler (and possibly assembler) in
- 1.0. This isn't entirely equivalent to ResEdit's CODE editor right now -- it
- just does the same thing as far as searching for references and such.
-
- -------------------------------------------------------------------------
- - Some examples of Janus in action, to give you a feel of how to use it.
-
- Case Study: Game-cheating patches to Pathways Into Darkness 2.0 (fat)
-
- Janus won't help you find the 68k code to patch, so I've provided the 68k patches
- already. I walk you through 2 patches, showing you how to find the native code
- corresponding to the patched areas and tell you how to patch them (w/ HexEdit).
- --------------------------
-
- First patch: We'd like to be invulnerable, so we need to axe the subtraction
- command at CODE 6+22B4 (which is done in the 680x0 code by NOP'ing it out). So
- let's try to find the corresponding code in the PPC native code.
-
- Unfortunately, CODE 6 doesn't have an trap calls in it, so we can't use the direct
- method (which would be looking for distinctive traps surrounding the code in
- question). We're interested in 6+22B4, which is closely followed by a JSR to
- CODE 3+1CBA. This looks a bit more promising, being preceded by some good
- traps.
-
- DrawString:
- 0x0000D46C
- 0x0000D52C
- 0x0000DCA4
- 0x0000DD6C
- 0x0000DE54
- 0x0000E878
- 0x0000E9E0
- 0x0000EB84
- 0x0000ED94
- 0x0000F4B8
- 0x0000F6A4
- 0x0000F7F0
- 0x0000FC24
- 0x0000FE78
- 0x000102A4
- 0x000103C0
- 0x00010A3C
- 0x00010A6C
- 0x00011098
- 0x000114F8
- 0x00015234 x
- 0x0001FB18 x
- 0x00022B08 x
-
- Well, that's a pretty large number, but we can eliminate the last three, since
- they're all fairly far from any other occurrence of DrawString. Still too
- many though...
-
- So let's look back a ways and see if there are any interesting traps. Too many
- StringWidths near DrawStrings to be of use... But the GetMainDevice and
- NewCWindow at 3+1966 and 3+19AC look good.
-
- GetMainDevice:
- 0x0000D1F8
- 0x0000D2A8
- 0x0000F910
- 0x0000F9B8
- 0x00010D70
- 0x00010DF4
- 0x00011688
- 0x000116B0
- 0x000129FC
- 0x00012BD8
- 0x00013BF0
- 0x00013FD0
- 0x000179A4
- 0x0002FCA0
- 0x0002FCC8
- 0x00031874
- 0x00031BBC
- 0x00031BE0
- 0x00032B4C
- 0x00032BD8
-
- NewCWindow:
- 0x0000D324
- 0x0000FA64
- 0x00010E68
- 0x00012AB4
- 0x00017A18
- 0x00022D64
-
- Hmm. I would've expected more NewCWindow's than GetMainDevices...
- Well, there's still a fair number left, so lets see how many of these have
- OffsetRects sandwiching the GetMainDevice. (Note the JSR code 2+20D0
- at 3+19BE = 0x0001DA3C...we'll use that for our next patch)
-
- OffsetRect: GetMainDevice: OffsetRect: GetMainDevice: OffsetRect: NewCWindow:
- (none) 0x0000D1F8 0x0000D2A0 0x0000D2A8 0x0000D2E0 0x0000D324 x
- 0x0000F978 0x0000F910 0x0000F9B0 0x0000F9B8 0x0000F9F0 0x0000FA64
- (none) 0x00010D70 0x00010DCC 0x00010DF4 0x00010E2C 0x00010E68 x
- (none) 0x000129F4 0x000129FC 0x00012A38 0x00012AB4 x
- (none) 0x00179A4 0x00017C8C 0x00017A18 x
- (none) 0x00022D64 x
-
- So now we know where 3+19AC is: 0x0000FA64. So let's look for
- subroutines after that. Well, we see the CloseWindow, but no SetWTitle...
- Well, let's just keep looking past this mammoth subroutine 'til we find another
- subroutine and try to regain our bearings. Ah, here's one at 0x0000FFC4.
- It does a GetPort, SetPort, SetRect, then a JSR. Well, that looks an awful lot
- like 3+1CBA, especially with the parameters passed to the JSR (0xE8 and
- 0x14). How convenient. (And yes, there is still some guesswork involved.)
-
- Now let's ask Janus & ResEdit what references there are to this subroutine:
- 0x0001040C 3+1A48
- 0x0002776C 6+076E
- 0x00029D54 6+20B8
- 0x00029EA8 6+21E2
- 0x0002A034 6+22D4
-
- Luckily enough, it's pretty obvious which subroutines here correlate to the
- references listed by ResEdit's CODE editor. We want 6+22D4, so let's look
- around 0x0002A034. Look up a little bit, and look, there's our subtraction
- command at 0x0002A004. Well, the easiest way to bypass this is to avoid the
- storage of the new value back in 60(R3), so NOP out that command.
-
- Change: 0x002A008 from 0xB0C30060 to 60000000
- Effect: Invulnerability. You still say "ouch", but you don't lose any health.
-
- --------------------------
- Second patch: Don't you hate having to be on the little red runes in order to
- save? Let's fix that. The 680x0 code is at CODE 2+0728. We need to axe
- the branch statement with a NOP.
-
- Well, it looks like we won't even need that CODE 2 we noticed above, since
- there's an OpenDeskAcc just above at 2+06EA. That's pretty distinctive.
- And sure enough, Janus only finds one occurrence of it at 0x000195A8.
-
- So we slowly work our way down both sets of code (a large monitor really
- helps here!). Notice that the method of implementing a jump table in PPC code
- is to use a blr instruction (being preceded by something other than mtlr R0).
-
- Well, the inline jump table could make things sticky, so let's look for the first
- occurrence of TickCount just after the OpenDeskAcc: 0x000195F8. Look
- above a little bit, past the branch and JSR and you see the branch we'd like
- to get rid of at 0x000195E4.
-
- Change: 0x000195E4 from 0x41820028 to 60000000
- Effect: You can save anywhere.
-
- --------------------------
- Some more patches you can practice on:
-
- Infinite crystal life: 7+3EE0 D16B 0004 -> 4E71 4E71
- Ammo-less monsters: 7+0610 4EBA 0C1C -> 4E71 4E71
- 7+11F4 4EBA 0038 -> 4E71 4E71
- Infinite ammo: 7+415A 9F6A 0004 -> 4E71 4E71
-
- And since CODE 7 doesn't contain any traps, you'll have to use the same kind of
- strategy I used for the first patch above...
-
- -------------------------------------------------------------------------
- - Epilogue
-
- If you have any questions, comments, suggestions, etc., feel free to send me
- e-mail at pjcreath@phoenix.princeton.edu
- - Peter
-
- -------------------------------------------------------------------------
- (Paranoid) DISCLAIMER:
-
- Layman's summary:
-
- The program should work, but if it crashes, you get what you pay for.
- I can't control what people do with this program, nor can I be held liable
- for their actions.
-
- Legalese:
-
- THE AUTHOR (Peter J. Creath) MAKES NO WARRANTY OR REPRESENTATION,
- EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THE SOFTWARE, ITS QUALITY,
- PERFORMANCE, MARCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
- AS A RESULT, THIS SOFTWARE AND ACCOMPANYING DOCUMENTATION IS
- PROVIDED "AS IS," AND YOU THE USER ARE ASSUMING THE ENTIRE RISK AS
- TO ITS QUALITY AND PERFORMANCE.
-
- IN NO EVENT WILL THE AUTHOR (Peter J. Creath) BE LIABLE FOR ANY
- CONSEQUENTIAL, INCIDENTAL OR INDIRECT DAMAGES (INCLUDING DAMAGES
- FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS
- INFORMATION, AND THE LIKE) ARISING OUT OF THE USE OF OR INABILITY TO USE
- THE SOFTWARE OR ACCOMPANYING DOCUMENTATION EVEN IF THE AUTHOR
- (Peter J. Creath) HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
- The author's liability for actual damages for any cause whatsoever,
- and regardless of the form of the action, will be limited to the purchase price
- of the Software ($0.00).
-